<?php

/**
 * PayPal支付
 * 数据表:paypal
 * id, ptype, url, sandboxurl, business, sandbox_business
 * @author freeflowf@gmail.com
 */
class Paypal {

    public $runType = 'complete';
    public $proxy = array(
        //测试
        'sandbox' => array(
            'host' => 'www.sandbox.paypal.com',
            'port' => 443,
            'ssl' => 'ssl://',
        ),
        //上线
        'complete' => array(
            'host' => 'www.paypal.com',
            'port' => 80,
            'ssl' => '',
        ),
    );
    public $logFp = false;
    public $orderNumber;
    public $paypalUrl = array(
        'sandbox' => array(
            'url' => 'https://www.sandbox.paypal.com/cgi-bin/webscr',
            'business' => 'hanbiji@qq.com',
        ),
        'complete' => array(
            'url' => 'https://www.paypal.com/cgi-bin/webscr',
            'business' => 'ufsell@gmail.com',
        ),
    );

    /**
     * IPN通信
     */
    public function ipn() {
        $paymentInfo = $this->getResponse();
        if ($this->postBack()) {
            $payment = Orders::model()->updateOrderPay($this->orderNumber, $paymentInfo);
            $this->log("\r\n修改支付状态：$payment");
            if ($paymentInfo['payment_status'] == 'Completed' && $paymentInfo['payment_amount'] > 0) {
                //发送数据到OA
                $this->reOaApi($paymentInfo['order_number']);
            } else {
                //支付状态发生变动, 发送信息到OA进行同步
                if ($paymentInfo['payment_amount'] < 0 && $paymentInfo['payment_status'] == 'Completed') {
                    $this->UpdateOaPaymentStatus($paymentInfo['order_number'], 'CB');
                } else {
                    $this->UpdateOaPaymentStatus($paymentInfo['order_number'], $paymentInfo['payment_status']);
                }
                
            }
        }else{
            $this->log("\r\n没有通过PAYPAL验证");
        }
    }

    /**
     * 成功返回网站
     */
    public function success() {
        $paymentInfo = $this->getResponse();
        if (!isset($_SESSION['txn_id']) || $_SESSION['txn_id'] != $paymentInfo['txn_id']) {
            $payment = Orders::model()->updateOrderPay($this->orderNumber, $paymentInfo);
            $this->log("\r\n修改支付状态：$payment");
            $_SESSION['txn_id'] = $paymentInfo['txn_id'];
            $_SESSION['payment'] = $payment;
        } else {
            $payment = $_SESSION['payment'];
        }

        return $payment;
    }

    public function getResponse() {
        //将 POST 变量记录在本地变量中
        //该付款明细所有变量可参考：
        //https://www.paypal.com/IntegrationCenter/ic_ipn-pdt-variable-reference.html
        $verify_sign = $_POST['verify_sign'];
        $business = $_POST['business'];
        $receiver_id = $_POST['receiver_id'];
        $receiver_email = $_POST['receiver_email']; //收款人主要EMAIL
        $orderNumber = $_POST['invoice']; //订单号
        $txn_id = $_POST['txn_id']; // paypal 交易号
        $payer_email = $_POST['payer_email']; //支付邮件
        $payer_id = $_POST['payer_id'];
        $payment_status = $_POST['payment_status']; //支付状态
        $payment_amount = $_POST['mc_gross']; //付款总额
        $payment_currency = $_POST['mc_currency']; //货币符号
        $payment_fee = $_POST['mc_fee']; //交易费用
        $payment_date = $_POST['payment_date'];
        $memo = $_POST['memo'];
        $address_country = $_POST['address_country']; //客户地址中的国家或地区
        $address_city = $_POST['address_city']; //城市
        $address_street = $_POST['address_street']; //街道
        $address_zip = $_POST['address_zip']; //
        $address_status = $_POST['address_status'];
        $contact_phone = $_POST['contact_phone'];
        $first_name = $_POST['first_name'];
        $last_name = $_POST['last_name'];
        $payer_status = $_POST['payer_status']; //客户的PAYPAL的状态

        $paymentInfo = array(
            'order_number' => $orderNumber,
            'business' => $business,
            'receiver_email' => $receiver_email,
            'receiver_id' => $receiver_id,
            'verify_sign' => $verify_sign,
            'payer_id' => $payer_id,
            'txn_id' => $txn_id,
            'payment_status' => $payment_status,
            'payer_email' => $payer_email,
            'payment_amount' => $payment_amount,
            'payment_currency' => $payment_currency,
            'payment_fee' => $payment_fee,
            'payment_date' => $payment_date,
            'memo' => $memo,
            'address_country' => $address_country,
            'address_city' => $address_city,
            'address_street' => $address_street,
            'address_zip' => $address_zip,
            'contact_phone' => $contact_phone,
            'address_status' => $address_status,
            'first_name' => $first_name,
            'last_name' => $last_name,
            'payer_status' => $payer_status,
            'type' => 'PayPal',
        );
        $this->orderNumber = $orderNumber;
        return $paymentInfo;
    }

    /**
     * 验证PAYPAL信息
     * @return boolean 
     */
    public function postBack() {
        //从 PayPal 出读取 POST 信息同时添加变量„cmd‟
        $postBack = 'cmd=_notify-validate';
        foreach ($_POST as $key => $value) {
            $value = urlencode(stripslashes($value));
            $postBack .= "&$key=$value";
        }
        //建议在此将接受到的信息记录到日志文件中以确认是否收到 IPN 信息
        //将信息 POST 回给 PayPal 进行验证
        $header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
        $header .= "Host: ".$this->proxy[$this->runType]['host']."\r\n";
        $header .= "Content-type:application/x-www-form-urlencoded\r\n";
        $header .= "Content-length:" . strlen($postBack) . "\r\n";
        $header .= "Connection: close\r\n\r\n";
        $fp = @fsockopen($this->proxy[$this->runType]['ssl'] . $this->proxy[$this->runType]['host'], $this->proxy[$this->runType]['port'], $errno, $errstr, 30);

        $this->log("PAYPAL返回内容\r\n" . print_r($_POST, true));
        $return = false;

        if (!$fp) {
            //HTTP 错误
            $this->log("\r\n HTTP 错误");
        } else {
            //将回复 POST 信息写入 SOCKET 端口
            fputs($fp, $header . $postBack);
            //开始接受 PayPal 对回复 POST 信息的认证信息
            while (!feof($fp)) {
                $res = fgets($fp, 1024);
                //返回内容
                $this->log($res . "\r\n");
                //已经通过认证
                //$this->log("\r\n".strcmp(strtoupper($res), "VERIFIED"));
                if (strcmp(strtoupper($res), "VERIFIED") == 0 || strcmp(strtoupper($res), "VERIFIED") == 20 || strtoupper(trim($res)) == "VERIFIED") {
                    //检查付款状态 VERIFIED
                    //检查 txn_id 是否已经处理过
                    //检查 receiver_email 是否是您的 PayPal 账户中的 EMAIL 地址
                    $return = true;
                    $this->log("\r\n=============================");
                    $this->log("\r\n通过认证");
                } else if (strcmp(strtoupper($res), "INVALID") == 0) {
                    //未通过认证，有可能是编码错误或非法的 POST 信息
                    $this->log("\r\n=============================");
                    $this->log("\r\n未通过认证，有可能是编码错误或非法的 POST 信息");
                }
                
            }
            fclose($fp);
        }

        return $return;
    }

    /**
     * 记录日志
     * @param string $message 
     */
    public function log($message) {
        //日志记录
        if (!$this->logFp) {
            $this->logFp = @fopen(Yii::app()->basePath . '/runtime/payLog/' . $_POST['invoice'] . '.log', 'a+');
        }

        @fwrite($this->logFp, $message);
        //fwrite($this->logFp, "\r\n=============================");
    }

    /**
     * 支付成功发送数据到OA接口
     */
    public function reOaApi($orderNumber) {
        /*
         * 单机版停止单位推送功能
        $req = 'cmd=_save_order';
        $orderModel = new Orders;
        $data = $orderModel->getOrderByNumberAll($orderNumber);
        $orderId = $data['base']['id'];
        $order = serialize($data);
        $order = urlencode($order);
        $req .= "&order=$order";

        $header .= "POST /oaApi.php HTTP/1.0\r\n";
        $header .= "Content-Type:application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length:" . strlen($req) . "\r\n\r\n";

        //连接到OA
        $fp = fsockopen('localhost', 8080, $errno, $errstr, 30);

        if (!$fp) {
            //echo 'http ERROR!';
        } else {

            fputs($fp, $header . $req);

            while (!feof($fp)) {
                $res = fgets($fp, 1024);
                if (strcmp(strtoupper($res), "ORDERSUCCESS") == 0) {
                    //保存成功, 修改订单状态
                    Orders::model()->updateByPk($orderId, array('status' => 'OE'));
                }
            }
            fclose($fp);
        }
        
        //推送其它未成功接收的订单
        foreach ($orderModel->findAll("(status='NW' AND pay_type='westernunion') OR (status='NW' AND pay_status='PY')") as $v) {
            $req = 'cmd=_save_order';
            $data = $orderModel->getOrderByNumberAll($v->order_number);
            $orderId = $data['base']['id'];
            $order = serialize($data);
            $order = urlencode($order);
            $req .= "&order=$order";

            $header = "POST /oaApi.php HTTP/1.0\r\n";
            $header .= "Content-Type:application/x-www-form-urlencoded\r\n";
            $header .= "Content-Length:" . strlen($req) . "\r\n\r\n";

            //连接到OA
            $fp = fsockopen('localhost', 8080, $errno, $errstr, 30);

            if (!$fp) {
                echo 'http ERROR!';
            } else {

                fputs($fp, $header . $req);

                while (!feof($fp)) {
                    $res = fgets($fp, 1024);
                    if (strcmp(strtoupper($res), "ORDERSUCCESS") == 0) {
                        //保存成功, 修改订单状态
                        Orders::model()->updateByPk($orderId, array('status' => 'OE'));
                    }
                }
                fclose($fp);
            }
            
        }
         * 
         */
        
    }

    //修改支付状态
    public function UpdateOaPaymentStatus($orderNumber, $paymentStatus) {
        $req = 'cmd=_update_payment';
        $orderNumber = urlencode($orderNumber); //订单号
        $paymentStatus = urlencode($paymentStatus); //支付状态
        $req .= "&orderNumber=$orderNumber&paymentStatus=$paymentStatus";

        $header .= "POST /oaApi.php HTTP/1.0\r\n";
        $header .= "Content-Type:application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length:" . strlen($req) . "\r\n\r\n";

        //连接到OA
        $fp = fsockopen('220.178.83.90', 8080, $errno, $errstr, 30);

        if (!$fp) {
            //echo 'http ERROR!';
        } else {

            fputs($fp, $header . $req);

            while (!feof($fp)) {
                $res = fgets($fp, 1024);
                if (strcmp(strtoupper($res), "SUCCESS") == 0) {
                    //保存成功
                    //Orders::model()->updateByPk($orderId, array('status' => 'OE'));
                }
            }
            fclose($fp);
        }
    }
    
    

}

//file end.